﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Text.RegularExpressions;

namespace AMStudio.Driver
{
    public enum TagDataType
    {
        Discrete,
        Integer,
        Real,
        String,
    }
    public enum TagDirection
    {
        Writable,
        Readable,
        Both,
    }
    [Serializable]
    public class PLCPortsTag
    {
        private string rTDBTag;
        public string RTDBTag
        {
            get { return rTDBTag; }
            set { rTDBTag = value; }
        }

        private string regType;
        public string RegType
        {
            get { return regType; }
            set { regType = value; }
        }

        private TagDataType dataType;
        public TagDataType DataType
        {
            get { return dataType; }
            set { dataType = value; }
        }

        private int length;
        public int Length
        {
            get { return length; }
            set { length = value; }
        }

        private int blockAddr;
        public int BlockAddr
        {
            get { return blockAddr; }
            set { blockAddr = value; }
        }

        private int startAddr;
        public int StartAddr
        {
            get { return startAddr; }
            set { startAddr = value; }
        }

        private int index;
        public int Index
        {
            get { return index; }
            set { index = value; }
        }

        private string name;
        public string Name
        {
            get { return name; }
            set { name = value; }
        }

        private TagDirection direction;
        public TagDirection Direction
        {
            get { return direction; }
            set { direction = value; }
        }

        private string readMode;
        public string ReadMode
        {
            get { return readMode; }
            set { readMode = value; }
        }

        private string modules;
        public string Modules
        {
            get { return modules; }
            set { modules = value; }
        }

        private string comments;
        public string Comments
        {
            get { return comments; }
            set { comments = value; }
        }

        internal bool IsBitType = false;
        internal bool AlreadyReadForCycle = false;

        internal bool RisingEdgeDetectedInCurrentCycle = false;
        internal bool FallingEdgeDetectedInCurrentCycle = false;

        internal byte[] ByteData = null;
        internal PLCPortsTag ParentTag = null;
        private object mValue = null;

        public void SetData(object value)
        {
            if (this.IsBitType)
            {
                bool flag = (bool)value;
                this.ByteData[0] = flag ? ((byte)1) : ((byte)0);
            }
            else
            {
                if (length == 1)
                {
                    int num = (int)value;
                    for (int i = 0; i < length; i++)
                    {
                        ByteData[2 * i] = (byte)(num >> 8);
                        ByteData[2 * i + 1] = (byte)(num & 0xffL);
                    }
                }
                else
                {
                    int[] num = (int[])value;
                    for (int i = 0; i < length; i++)
                    {
                        ByteData[2 * i] = (byte)(num[i] >> 8);
                        ByteData[2 * i + 1] = (byte)(num[i] & 0xffL);
                    }
                }
            }
            AlreadyReadForCycle = false;
            //mValue = value;
        }
        public void SetData(string value)
        {
            if (this.IsBitType)
            {
                bool flag = bool.Parse(value);
                this.ByteData[0] = flag ? ((byte)1) : ((byte)0);
            }
            else
            {
                if (length == 1)
                {
                    int num = int.Parse(value);
                    for (int i = 0; i < length; i++)
                    {
                        ByteData[2 * i] = (byte)(num >> 8);
                        ByteData[2 * i + 1] = (byte)(num & 0xffL);
                    }
                }
                else
                {
                    int[] v = new int[length];
                    string[] r = value.Split(',');
                    for (int i = 0; i < v.Length; i++)
                    {
                        v[i] = int.Parse(r[i]);
                    }
                    for (int i = 0; i < length; i++)
                    {
                        ByteData[2 * i] = (byte)(v[i] >> 8);
                        ByteData[2 * i + 1] = (byte)(v[i] & 0xffL);
                    }
                }
            }
            AlreadyReadForCycle = false;
            //mValue = value;
        }
        public object GetData()
        {
            if (this.IsBitType)
            {
                int intRes = 0;
                intRes += ((int)ByteData[0]) << 8;
                intRes += ByteData[1];
                GetBitValueAndSetEdgeSignal(intRes, index);
            }
            else
            {
                if (length == 1)
                {
                    int intRes = 0;
                    for (int i = 0; i < length; i++)
                    {
                        intRes += ((int)ByteData[2 * i]) << 8;
                        intRes += ByteData[2 * i + 1];
                    }
                    mValue = intRes;
                }
                else
                {
                    int[] v = new int[length];
                    //ByteData = new byte[2 * length];
                    for (int i = 0; i < length; i++)
                    {
                        v[i] += ((int)ByteData[2 * i]) << 8;
                        v[i] += ByteData[2 * i + 1];
                    }
                    mValue = v;
                }
            }
            return mValue;
        }

        private void GetBitValueAndSetEdgeSignal(int value, int addr)
        {
            if (!this.AlreadyReadForCycle)
            {
                bool currentValue = GetBitValue(value, index);
                if (mValue != null)
                {
                    bool oldValue = (bool)mValue;
                    if (currentValue)
                    {
                        FallingEdgeDetectedInCurrentCycle = false;
                        if (!oldValue)
                        {
                            RisingEdgeDetectedInCurrentCycle = true;
                        }
                        else
                        {
                            RisingEdgeDetectedInCurrentCycle = false;
                        }
                    }
                    else
                    {
                        RisingEdgeDetectedInCurrentCycle = false;
                        if (oldValue)
                        {
                            FallingEdgeDetectedInCurrentCycle = true;
                        }
                        else
                        {
                            FallingEdgeDetectedInCurrentCycle = false;
                        }
                    }
                }
                mValue = currentValue;
            }
            else
            {
                mValue = GetBitValue(value, index);
            }
        }
        private bool GetBitValue(int value, int addr)
        {
            //if (addr > 7)
            //{
            //    addr = addr - 8;
            //    value = (int)(value & 0xffL);
            //}
            //else
            //{
            //    value = value >> 8;
            //}
            addr = 1 << addr;
            if ((value & addr) > 0)
            {
                return true;
            }
            ////if (((value & (1 << (addr & 0x1f))) >> addr) != 1)
            ////{
            ////    return false;
            ////}
            return false;
        }

        public void GetSubTagValue(PLCPortsTag subTag)
        {
            int offset = (subTag.StartAddr - this.StartAddr) * 2;
            //int length = this.Length*2 - offset;
            //subTag.ByteData = new byte[length];
            Array.Copy(this.ByteData, offset, subTag.ByteData, 0, subTag.ByteData.Length);
        }
    }
}
